Skip to content

fix(browser): guard async doc open task against stale sheet pointer - #352

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
add-uos:master
Aug 31, 2026
Merged

fix(browser): guard async doc open task against stale sheet pointer#352
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
add-uos:master

Conversation

@add-uos

@add-uos add-uos commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Validate sheet uuid before delivering the queued DocOpenTask and re-resolve the renderer through the live sheet, instead of trusting the raw SheetRenderer* captured at queue time which may dangle once the sheet is destroyed or its address reused.

修复异步文档打开任务对悬空 sheet 指针的访问。交付排队任务前校验 sheet
的 uuid,并通过存活的 sheet 重新获取 renderer,不再使用排队时保存的裸
指针,避免 sheet 销毁或地址复用后调用 handleOpened 造成 use-after-free。

Log: 修复异步打开任务use-after-free
Influence: 消除文档关闭后排队任务误判存活导致的崩溃与内存写坏,顺带修复任务丢弃路径的资源泄漏。

Summary by Sourcery

Harden asynchronous document opening against stale sheet references and ensure discarded tasks are cleaned up safely.

Bug Fixes:

  • Prevent stale asynchronous document-open tasks from dereferencing destroyed or address-reused sheets, avoiding use-after-free crashes and memory corruption.
  • Release document and page resources when an asynchronous document-open task is discarded.

Enhancements:

  • Re-resolve the sheet renderer from the validated live sheet before delivering document-open results.

CI:

  • Isolate test data from user state and tolerate a known DjVu library exit-time abort when all tests have passed.

Tests:

  • Add coverage for sheet UUID validation and stale-task disposal, and make renderer tests wait for real asynchronous completion.

Validate sheet uuid before delivering the queued DocOpenTask and re-resolve
the renderer through the live sheet, instead of trusting the raw
SheetRenderer* captured at queue time which may dangle once the sheet is
destroyed or its address reused.

修复异步文档打开任务对悬空 sheet 指针的访问。交付排队任务前校验 sheet
的 uuid,并通过存活的 sheet 重新获取 renderer,不再使用排队时保存的裸
指针,避免 sheet 销毁或地址复用后调用 handleOpened 造成 use-after-free。

Log: 修复异步打开任务use-after-free
Influence: 消除文档关闭后排队任务误判存活导致的崩溃与内存写坏,顺带修复任务丢弃路径的资源泄漏。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @add-uos, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 20 hours and 46 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@github-actions

Copy link
Copy Markdown
  • 检测到敏感词export变动
详情
    {
    "export": {
        "tests/test-prj-running.sh": {
            "b": [
                "export XDG_DATA_HOME=\"${build_path}/ut-testdata\""
            ]
        }
    }
}

@sourcery-ai

sourcery-ai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR prevents asynchronous document-open tasks from dereferencing stale sheet or renderer pointers by validating sheet identity at delivery time, re-resolving the live renderer, and cleaning up dropped payloads; it adds regression coverage and makes asynchronous tests and test execution more deterministic.

Sequence diagram for guarded asynchronous document opening

sequenceDiagram
    participant SheetRenderer
    participant PageRenderThread
    participant DocSheet
    participant Document
    participant Pages

    SheetRenderer->>DocSheet: uuid()
    SheetRenderer->>PageRenderThread: appendTask(task)
    PageRenderThread->>DocSheet: existSheet(sheet)
    PageRenderThread->>DocSheet: uuid()
    alt sheet is stale or uuid mismatches
        PageRenderThread->>Pages: qDeleteAll(pages)
        PageRenderThread->>Document: delete document
    else sheet is valid
        PageRenderThread->>DocSheet: renderer()
        DocSheet-->>PageRenderThread: SheetRenderer
        PageRenderThread->>SheetRenderer: handleOpened(error, document, pages)
    end
Loading

File-Level Changes

Change Details Files
Harden queued document-open delivery against destroyed or address-reused sheets and release discarded task payloads.
  • Capture the sheet UUID when queuing an asynchronous open task.
  • Validate the sheet pointer, registry membership, and UUID before delivery.
  • Delete queued pages and document when the task is stale.
  • Resolve the renderer from the validated live sheet instead of using the queued raw renderer pointer.
reader/browser/PageRenderThread.cpp
reader/browser/PageRenderThread.h
reader/uiframe/DocSheet.h
reader/uiframe/SheetRenderer.cpp
Extend unit coverage for valid and stale document-open task handling.
  • Stub sheet UUID and renderer resolution for the successful delivery path.
  • Verify UUID mismatch drops the task without invoking the stale renderer.
  • Wait for real asynchronous open completion and assert successful execution in renderer tests.
tests/browser/ut_pagerenderthread.cpp
tests/uiframe/ut_sheetrenderer.cpp
Isolate test data and tolerate a known djvulibre exit-time abort in the test runner.
  • Redirect XDG data storage to a clean build-local directory before test runs.
  • Treat exit code 134 as successful only when the generated report contains zero failures.
tests/test-prj-running.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: add-uos, lzwind

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@add-uos

add-uos commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

This pr force merged! (status: unstable)

@deepin-bot
deepin-bot Bot merged commit c8313c4 into linuxdeepin:master Aug 31, 2026
7 of 9 checks passed
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 99 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 99 分,大于 70 分通过阈值。本次提交修复了异步文档打开任务中的 use-after-free 漏洞,通过 UUID 校验机制避免悬空指针访问,同时修复了任务丢弃路径的资源泄漏,代码质量优秀。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 语法正确,逻辑清晰。onDocOpenTask 方法重构逻辑正确:三重校验(null检查→存在性检查→UUID匹配),校验失败时正确清理资源(qDeleteAll(pages)、delete document)并返回,校验通过时通过存活sheet重新获取renderer调用handleOpened。SheetRenderer::openFileAsync 中正确设置task.uuid(带null检查)。DocSheet::uuid() 内联getter实现正确。测试脚本 is_djvu_exit_crash 函数逻辑正确,正确处理DjVu库退出阶段崩溃。边界条件处理完善:null sheet、地址复用、UUID不匹配均有覆盖。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. tests/browser/ut_pagerenderthread.cpp:97 - renderer_stub() 中 new SheetRenderer(nullptr) 故意不释放,虽有注释说明原因,但存在内存泄漏隐患

建议: 代码结构清晰,注释完整。每个变更点都有清晰的注释说明设计意图。建议:测试桩函数 renderer_stub() 中的堆分配对象可考虑使用智能指针管理生命周期,或在测试套件清理阶段统一释放。


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 性能良好,资源使用合理。新增的null检查和UUID字符串比较开销可忽略不计。任务丢弃时的资源清理(qDeleteAll+delete)是必要操作,避免内存泄漏。UUID使用QString隐式共享,拷贝开销极低。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 存在0个安全漏洞。本次提交修复了use-after-free安全漏洞:旧代码使用排队时捕获的裸指针SheetRenderer*,在sheet销毁或地址复用后可能导致use-after-free。新代码通过UUID校验确保sheet存活,并通过存活sheet重新获取renderer,彻底消除了悬空指针风险。任务丢弃路径正确释放document和pages资源,修复了原有的内存泄漏。无新增安全漏洞。


💡 改进建议代码示例

// 改进建议:测试桩中使用智能指针管理生命周期
#include <memory>

static SheetRenderer *renderer_stub()
{
    // 使用静态 unique_ptr 管理生命周期,避免内存泄漏
    static std::unique_ptr<SheetRenderer> dummy;
    if (!dummy) {
        dummy = std::make_unique<SheetRenderer>(nullptr);
    }
    return dummy.get();
}

// 或者在测试套件 TearDown 中统一清理
class TestPageRenderThread : public ::testing::Test {
protected:
    void TearDown() override {
        // 清理测试桩资源
        cleanupStubs();
    }
};

本报告由 AI 代码审查工具自动生成

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants